<?php

declare( strict_types = 1 );

namespace App\Common\Model\Base;

use App\Common as com;
use App\Common\Model as nameModel;
use App\Common\Model\Base\DataUnit as nameDataUnit;
use App\Common\Lib\Hyperf\QueryExtend as nameQueryExtend;
use Carbon\Carbon;

class DataUnit {

	use nameDataUnit\DataOperate\Traits;

	use com\Lib\Com\GoWeakReferencePool\Traits;

	// 引入数据操作接口
	use com\Cla\ClaBase\Traits\GoPool;

	/**
	 * dataUnit模式->正常
	 * @var int
	 */
	public static int $varDataUnitMode_Normal = 0;

	/**
	 * dataUnit模式->创建
	 * @var int
	 */
	public static int $varDataUnitMode_OnlyCreate = 1;

	/**
	 * dataUnit模式->修改
	 * @var int
	 */
	public static int $varDataUnitMode_OnlyUpdate = 2;

	/**
	 * @var int|null
	 */
	protected ?int $_dataIdOrNull = null;

	/**
	 * __construct中的$dataIdOrWhere参数
	 * @var array|int|null
	 */
	protected array|int|null $initParamDataIdOrWhere;

	/**
	 * dataUnit模式
	 * @var int [self::$varDataUnitMode_Normal]正常 [self::$varDataUnitMode_OnlyCreate]创建 [self::$varDataUnitMode_OnlyUpdate]修改
	 */
	private int $_dataUnitMode = 0;

	/**
	 * 表名
	 * @var string
	 */
	private string $_tableName;

	/**
	 * 表DataUnit路径
	 * @var string
	 */
	protected string $_modelDataUnitClassPath;

	/**
	 * field
	 * @var array
	 */
	private array $mustRetainFields = [];

	/**
	 * 临时field
	 * @var array
	 */
	private array $tempFields = [];

	/**
	 * field清理初始化数据
	 * @var array|null
	 */
	private ?array $fieldClearInitData = null;

	/**
	 * 数据数据字段列表
	 * @var array
	 */
	private array $recordDataFields;

	/**
	 * 自定义模型地址
	 * @var string|null
	 */
	protected ?string $config_ModelPartClassPath = null;

	/**
	 * @var bool
	 */
	private bool $isCleanAllData = false;

	/**
	 * @param array|int|null $dataIdOrWhere id或where条件
	 * @throws
	 */
	public function __construct( array|int|null $dataIdOrWhere = null ) {
		$this->initParamDataIdOrWhere = $dataIdOrWhere;
		//
		$this->resetModelClassPath( $this->config_ModelPartClassPath ?? static::class );
		//
		if( is_array( $dataIdOrWhere ) ){
			$this->setWhereOfUnique( $dataIdOrWhere );
		} else if( is_numeric( $dataIdOrWhere ) ){
			// $this->_dataIdOrNull = $dataIdOrWhere;
			$this->setDataId( $dataIdOrWhere );
		} else if( $dataIdOrWhere !== null ){
			throw com\Lib\Err\Exception::makeOfNew( '参数类型错误', com\Lib\Err\Code::$sysFunParamError );
		}
		//
		$this->callInitTraitDataUnit();
	}

	/**
	 * 执行init
	 */
	private function callInitTraitDataUnit() {
		if( method_exists( $this, '_initTraitDataUnit' ) ){
			call_user_func( [
				$this,
				'_initTraitDataUnit'
			] );
		}
	}

	/**
	 * new自身(不带where等数据)
	 * @return $this
	 */
	public function newSelf():self {
		$class = static::class;
		return new $class;
	}


	/**
	 * new自身并保留where属性
	 * @return $this
	 */
	public function newSelfCloneWhere():self {
		$newDataUnit = $this->newSelf();
		// $newDataUnit->setModelQuery( $this->goModelQueryCloneWhereOfNew() );
		$newDataUnit->setModelQuery( $this->goModelQueryCloneOfNew() );
		return $newDataUnit;
	}

	/**
	 * new自身并保留其他属性
	 * @return $this
	 */
	/*
	public function newSelfClone(  ):self {
		$newDataUnit = $this->newSelf();
		$newDataUnit->setModelQuery( $this->goModelQueryCloneOfNew() );
		return $newDataUnit;
	}
	*/

	/**
	 * @return array
	 */
	public function getDataOperateData():array {
		return $this->_dataOperate_Data;
	}

	/**
	 * 设置模型类地址
	 * @param string $classPath
	 */
	private function resetModelClassPath( string $classPath ):void {
		$this->_modelDataUnitClassPath = $this->analysisModelClassPath( $classPath ) . "\DataUnit";
	}

	/**
	 * 设置数据id
	 * @param int $dataId
	 * @return $this
	 */
	public function setDataId( int $dataId = null ):self {
		/*
		if( $this->_dataIdOrNull !== null ){
			throw com\Lib\Err\Exception::makeOfNew( '不可重复设置dataId' );
		}
		*/
		$this->_dataIdOrNull = $dataId;
		if( $this->_dataIdOrNull !== null ){
			// $this->goModelQuery()->where( $this->getTableName() . '.id', '=', $this->_dataIdOrNull );
			$this->where( 'id', '=', $this->_dataIdOrNull );
		}
		//
		return $this;
	}

	/**
	 * 设置数据where
	 * @param array $where
	 * @return $this
	 */
	private function setWhereOfUnique( array $where ):self {
		$this->goModelQuery()->where( $where );
		//
		return $this;
	}

	/**
	 * 是否为创建数据模式
	 * @return bool
	 */
	public function isCreate():bool {
		return empty( $this->goModelQuery()->getQuery()->wheres );
	}

	/**
	 * 获取主键id->主数据id 或 null
	 * @return int|null
	 */
	public function getDataIdOrNull():?int {
		if( $this->_dataIdOrNull === null && ! $this->isCreate() ){
			$this->setDataId( $this->isExistToIdOrNull() );
		}
		//
		return $this->_dataIdOrNull;
	}

	/**
	 * 获取数据id(如数据id不存在，则抛出异常)
	 * @return int
	 */
	public function getDataIdOrFail():int {
		$dataId = $this->getDataIdOrNull();
		if( $dataId === null ){
			$tableName = $this->getTableName();
			throw com\Lib\Err\Exception::makeOfNew( "数据不存在({$tableName})", com\Lib\Err\Code::$sysDataError );
		}
		return $dataId;
	}

	public function gowDirectData():nameDataUnit\DirectData {
		return $this->goPool( __FUNCTION__, function () {
			return new nameDataUnit\DirectData( $this );
		} );
	}

	/**
	 * 获取表名
	 * @return string
	 */
	public function getTableName():string {
		if( ! isset( $this->_tableName ) ){
			/*
			$tableName = substr( $this->getModelClassPath(), strrpos( $this->getModelClassPath(), '\\' ) + 1 );
			$this->_tableName = com\Lib\Fun\Str::parseName( $tableName );
			*/
			$this->_tableName = $this->goModelQuery()->getModel()->getTable();
		}
		return $this->_tableName;
	}

	/**
	 * 获取表名(完整表名，带前缀)
	 * @return string
	 */
	public function getTableNameAsPrefix():string {
		return \Hyperf\Support\env( 'DB_PREFIX', '' ) . $this->getTableName();
	}

	/**
	 * 解析model类路径
	 * @param string $path
	 * @return string
	 */
	private function analysisModelClassPath( string $path ):string {
		$num = strpos( $path, '\\', 17 );
		if( $num !== false ){
			return substr( $path, 0, $num !== false ? $num : null );
		} else{
			return substr( $path, 0 );
		}
	}

	/**
	 * 获取model类路径
	 * @return com\Model\Origin\OriginBase [string]
	 * @throws
	 */
	public function getModelClassPath():string {
		return $this->goPool( __FUNCTION__, function () {
			return $this->analysisModelClassPath( $this->_modelDataUnitClassPath );
		} );
	}

	/**
	 * 获取dataUnit模式
	 * @return int self::$varDataUnitMode_xxx
	 */
	public function getDataUnitMode():int {
		return $this->_dataUnitMode;
	}

	/**
	 * 是否可以创建数据
	 * @return bool
	 */
	public function isAllowCreate():bool {
		return $this->getDataUnitMode() == self::$varDataUnitMode_Normal || $this->getDataUnitMode() == self::$varDataUnitMode_OnlyCreate;
	}

	/**
	 * 是否可以修改数据
	 * @return bool
	 */
	public function isAllowUpdate():bool {
		return $this->getDataUnitMode() == self::$varDataUnitMode_Normal || $this->getDataUnitMode() == self::$varDataUnitMode_OnlyUpdate;
	}

	/**
	 * 设置 dataUnit 模式为：正常
	 * @return static
	 */
	public function setDataUnitModeOfNormal():static {
		$this->_dataUnitMode = self::$varDataUnitMode_Normal;
		//
		return $this;
	}

	/**
	 * 设置 dataUnit 模式为：创建模式
	 * @return static
	 */
	public function setDataUnitModeOfOnlyCreate():static {
		$this->_dataUnitMode = self::$varDataUnitMode_OnlyCreate;
		//
		return $this;
	}

	/**
	 * 设置 dataUnit 模式为：修改模式
	 * @return static
	 */
	public function setDataUnitModeOfOnlyUpdate():static {
		$this->_dataUnitMode = self::$varDataUnitMode_OnlyUpdate;
		//
		return $this;
	}

	/**
	 * go指定模块，如果不存在则抛出异常
	 * @param string $moduleName 模块名
	 * @return object 返回模块对象
	 * @throws
	 */
	private function goModulePool( string $moduleName ):object {
		return $this->goPool( "go{$moduleName}", function () use ( $moduleName ) {
			return $this->newModulePool( $moduleName );
		} );
	}

	/**
	 * new指定模块，如果不存在则抛出异常
	 * @param string $moduleName 模块名
	 * @return object 返回模块对象
	 * @throws
	 */
	private function newModulePool( string $moduleName ):object {
		$classPath = $this->_modelDataUnitClassPath . "\\{$moduleName}";
		//
		if( ! class_exists( $classPath ) ){
			throw com\Lib\Err\Exception::makeOfNew( "{$moduleName} Not Exist", com\Lib\Err\Code::$sysFileNotExist );
		}
		//
		return new $classPath( $this );
	}

	/**
	 * 是否存在指定模块
	 * @param string $moduleName 模块名
	 * @return bool 是否存在
	 */
	/*
	private function isExistModulePool( string $moduleName ):bool {
		$classPath = static::class . "\{$moduleName}";
		return class_exists( $classPath );
	}
	*/

	/**
	 * go option
	 * @return nameDataUnit\Option
	 */
	public function goOption():nameDataUnit\Option {
		return $this->goModulePool( 'Option' );
	}

	/**
	 * go Field
	 * @return nameDataUnit\Field
	 */
	public function goField():nameDataUnit\Field {
		return $this->goModulePool( 'Field' );
	}

	/**
	 * go Field
	 * @return nameDataUnit\SetData
	 */
	public function goSetData():nameDataUnit\SetData {
		return $this->goModulePool( 'SetData' );
	}

	/**
	 * 动态where
	 * @return nameDataUnit\WhereDy
	 */
	public function goWhereDy():nameDataUnit\WhereDy {
		// 每次进入 WhereDy 都清空缓存 // @TODO :o 以后可改成事件模式
		$this->gowDirectData()->clearCache();
		//
		return $this->goModulePool( 'WhereDy' );
	}

	/**
	 * join model
	 * @return nameDataUnit\JoinModel
	 */
	public function goJoinModel():nameDataUnit\JoinModel {
		return $this->goModulePool( 'JoinModel' );
	}

	/**
	 * join model
	 * @return nameDataUnit\JoinModelX
	 */
	public function goJoinModelX():nameDataUnit\JoinModelX {
		return $this->goModulePool( 'JoinModelX' );
	}

	/**
	 * 动态join
	 * @return nameDataUnit\JoinDy
	 */
	public function goJoinDy():nameDataUnit\JoinDy {
		return $this->goModulePool( 'JoinDy' );
	}

	/**
	 * fun
	 * @return nameDataUnit\Fun
	 */
	public function goFun():nameDataUnit\Fun {
		return $this->goModulePool( 'Fun' );
	}

	/**
	 * ModelVar
	 * @return nameDataUnit\Var_
	 */
	public function goVar():nameDataUnit\Var_ {
		return $this->goModulePool( 'Var_' );
	}

	/**
	 * ModelVar
	 * @return nameDataUnit\Set
	 */
	public function goSet():nameDataUnit\Set {
		return $this->goModulePool( 'Set' );
	}

	/**
	 * ModelVar
	 * @return nameDataUnit\GetData
	 */
	public function goGetData():nameDataUnit\GetData {
		return $this->goModulePool( 'GetData' );
	}

	/**
	 * ModelVar
	 * @return nameDataUnit\GetDataOfCache
	 */
	public function goGetDataOfCache():nameDataUnit\GetDataOfCache {
		return $this->goModulePool( 'GetDataOfCache' );
	}

	/**
	 * ModelVar
	 * @return nameDataUnit\GetDatasetOfCache
	 */
	public function goGetDatasOfCache():nameDataUnit\GetDatasetOfCache {
		return $this->goModulePool( 'GetDatasOfCache' );
	}

	/**
	 * ModelVar
	 * @return nameDataUnit\GetDatasetOfCache
	 */
	public function newGetDatasOfCache():nameDataUnit\GetDatasetOfCache {
		return $this->newModulePool( 'GetDatasOfCache' );
	}

	/**
	 * ModelVar
	 * @return nameDataUnit\FieldData
	 */
	public function goFieldData():nameDataUnit\FieldData {
		return $this->goModulePool( 'FieldData' );
	}

	/**
	 * ModelVar
	 * @return nameDataUnit\WhereData
	 */
	public function goWhereData():nameDataUnit\WhereData {
		return $this->goModulePool( 'WhereData' );
	}

	/**
	 * go 查询对象（goModelQuery）
	 * @param \Hyperf\Database\Model\Builder $query
	 * @return static
	 */
	public function setModelQuery( \Hyperf\Database\Model\Builder $query ):static {
		return $this->goPoolSet( 'goModelQuery', $query );
	}

	/**
	 * go 查询对象（goModelQuery）
	 * @return nameQueryExtend\Model\Builder
	 * @throws
	 */
	public function goModelQuery():\Hyperf\Database\Model\Builder {
		return $this->goPool( __FUNCTION__, function () {
			return $this->goModelQueryOfNew();
		} );
	}

	/**
	 *
	 * @param \Hyperf\Database\Query\Builder $query
	 * @return static
	 */
	public function setQuery( \Hyperf\Database\Query\Builder $query ):static {
		if( $query->from === null ){
			$query->from = $this->getTableName();
		}
		//
		$this->goModelQuery()->setQuery( $query );
		//
		return $this;
	}

	/**
	 * 重置模型
	 * @return static
	 */
	public function resetModelQuery():static {
		$this->goPoolUnset( 'goModelQuery' );
		//
		return $this;
	}

	/**
	 * go 查询对象（新建）
	 * @return nameQueryExtend\Model\Builder
	 */
	public function goModelQueryOfNew():\Hyperf\Database\Model\Builder {
		return $this->getModelClassPath()::query();
	}

	/**
	 * 模型(保留where)
	 * @return nameQueryExtend\Model\Builder
	 */
	public function goModelQueryCloneWhereOfNew():\Hyperf\Database\Model\Builder {
		$query = $this->goModelQueryOfNew();
		$query->getQuery()->wheres = $this->goModelQuery()->getQuery()->wheres;
		$query->getQuery()->bindings = $this->goModelQuery()->getQuery()->bindings;
		return $query;
	}

	/**
	 * 模型(保留所有参数)
	 * @return nameQueryExtend\Model\Builder
	 */
	public function goModelQueryCloneOfNew():\Hyperf\Database\Model\Builder {
		$query = $this->goModelQueryOfNew();
		$query->getQuery()->aggregate = $this->goModelQuery()->getQuery()->aggregate;
		$query->getQuery()->columns = $this->goModelQuery()->getQuery()->columns;
		$query->getQuery()->joins = $this->goModelQuery()->getQuery()->joins;
		$query->getQuery()->wheres = $this->goModelQuery()->getQuery()->wheres;
		$query->getQuery()->bindings = $this->goModelQuery()->getQuery()->bindings;
		$query->getQuery()->groups = $this->goModelQuery()->getQuery()->groups;
		$query->getQuery()->havings = $this->goModelQuery()->getQuery()->havings;
		$query->getQuery()->orders = $this->goModelQuery()->getQuery()->orders;
		$query->getQuery()->limit = $this->goModelQuery()->getQuery()->limit;
		$query->getQuery()->offset = $this->goModelQuery()->getQuery()->offset;
		$query->getQuery()->unions = $this->goModelQuery()->getQuery()->unions;
		$query->getQuery()->unionLimit = $this->goModelQuery()->getQuery()->unionLimit;
		$query->getQuery()->unionOffset = $this->goModelQuery()->getQuery()->unionOffset;
		$query->getQuery()->lock = $this->goModelQuery()->getQuery()->lock;
		//
		// 复制保护属性->获取旧数据
		$classDatas = [];
		$fn = function ( $query ) use ( &$classDatas ) {
			// \Hyperf\Database\Model\Builder
			/** @phpstan-ignore-next-line */
			$classDatas['scopes'] = $query->scopes;
			/** @phpstan-ignore-next-line */
			$classDatas['removedScopes'] = $query->removedScopes;

		};
		call_user_func_array( $fn->bindTo( $this, get_class( $this->goModelQuery() ) ), [ $this->goModelQuery() ] );
		// 复制保护属性->覆盖新对象
		$fn2 = function ( \Hyperf\Database\Model\Builder $query ) use ( $classDatas ) {
			foreach( $classDatas as $classDataKey => $classData ){
				$query->$classDataKey = $classData;
			}
		};
		call_user_func_array( $fn2->bindTo( $fn2, get_class( $query ) ), [ $query ] );
		//
		return $query;
	}

	/**
	 * 判断数据是否存在
	 * @return bool [false]不存在 [true]存在
	 */
	public function isExist():bool {
		return (bool)$this->isExistToIdOrNull();
	}

	/**
	 * 判断数据是否存在，不存在则抛出异常
	 * @param string $errMsg 异常的msg提示
	 * @return bool
	 * @throws
	 */
	public function isExistOrFail( string $errMsg = '数据不存在' ):bool {
		if( $this->isExist() ){
			return true;
		} else{
			throw com\Lib\Err\Exception::makeOfNew( $errMsg, com\Lib\Err\Code::$sysDataNotExist );
		}
	}

	/**
	 * 判断数据是否存在，存在则返回主键id
	 * @return int|null [null]不存在 [>0]存在，并返回主键id
	 */
	public function isExistToIdOrNull():?int {
		return $this->goModelQuery()->value( 'id' ) ?? null;
	}

	/**
	 * 判断数据是否存在，存在则返回主键id，不存在则抛出异常
	 * @return int [>0]存在，并返回主键id
	 * @throws
	 */
	public function isExistToIDOrFail():int {
		$dataId = $this->isExistToIdOrNull();
		if( $dataId == 0 ){
			throw com\Lib\Err\Exception::makeOfNew( '数据不存在', com\Lib\Err\Code::$sysDataNotExist );
		}
		return $dataId;
	}

	/**
	 * go 分页模块
	 * @return nameDataUnit\Paginate
	 * @throws
	 */
	public function goPaginate():nameDataUnit\Paginate {
		return $this->goPool( 'goPaginate', function () {
			return new nameDataUnit\Paginate( $this );
		} );
	}

	/**
	 * 获取field
	 * 可能返回 null, [ 'id', ... ]
	 * 备注：当底层columns === [ '*' ]时，本方法会自动转换为null
	 * @return array|null
	 */
	public function getField():?array {
		$columns = $this->goModelQuery()->getQuery()->columns;
		if( $columns === [ '*' ] ){
			return null;
		} else{
			return $columns;
		}
	}

	/**
	 * field（通过该方法添加的field不会被自动销毁）
	 * @param string $field
	 * @return $this
	 */
	public function addFieldRaw( $field ):self {
		$this->goModelQuery()->selectRaw( $field );
		//
		return $this;
	}

	/**
	 * field（通过该方法添加的field不会被自动销毁）
	 * @param array|string $field
	 * @param bool $isAutoAlias 字符获取field别名。 [true][必定]
	 * @param bool $isRetain 是否强制保留 [false]否 [true][默认]是
	 * @return $this
	 */
	public function addField( array|string $field, bool $isAutoAlias = true, bool $isRetain = true ):self {
		//
		/*		if( is_array( $field ) ){
					$field = com\Lib\Fun\Str::parseNames( $field );
				}else{
					$field = com\Lib\Fun\Str::parseName( $field );
				}*/
		$fieldOld = $field;
		// 自动转换别名
		if( $isAutoAlias ){
			$field = $this->getFieldAlias( $field );
		}
		//
		if( $isRetain ){
			// $this->mustRetainField = com\Lib\Fun\Array_::arrayMerges( $this->mustRetainField, is_array( $field ) ? $field : [ $field ] );
			$this->mustRetainFields = com\Lib\Fun\Array_::arrayMerges( $this->mustRetainFields, is_array( $fieldOld ) ? $fieldOld : [ $fieldOld ] );
		}
		//
		$this->goModelQuery()->addSelect( $field );
		//
		return $this;
	}

	/**
	 * field（通过该方法添加的field不会被自动销毁）
	 * @param string $field
	 * @param string|null $as 别名
	 * @param bool $isAutoAlias 字符获取field别名。 [true][必定]
	 * @param bool $isRetain 是否强制保留 [false]否 [true][默认]是
	 * @return $this
	 */
	public function addFieldOneAs( string $field, string|null $as = null, bool $isAutoAlias = true, bool $isRetain = true ):self {
		$fieldOld = $field;
		// 自动转换别名
		if( $isAutoAlias ){
			$field = $this->getFieldAlias( $field );
		}
		//
		if( $isRetain ){
			// $this->mustRetainField = com\Lib\Fun\Array_::arrayMerges( $this->mustRetainField, is_array( $field ) ? $field : [ $field ] );
			if( $as === null ){
				$this->mustRetainFields = com\Lib\Fun\Array_::arrayMerges( $this->mustRetainFields, [ $fieldOld ] );
			} else{
				$this->mustRetainFields = com\Lib\Fun\Array_::arrayMerges( $this->mustRetainFields, [ $as ] );
			}

		}
		//
		if( $as === null ){
			$this->goModelQuery()->addSelect( $field );
		} else{
			$this->goModelQuery()->addSelect( "{$field} as {$as}" );
		}

		//
		return $this;
	}

	/**
	 * field（通过该方法添加的field不会被自动销毁）
	 * @param array|string $field
	 * @param bool $isAutoAlias 字符获取field别名。 [true][必定]
	 * @param bool $isRetain 是否强制保留 [false]否 [true][默认]是
	 * @return $this
	 */
	public function fieldAndReset( array|string $field, bool $isAutoAlias = true, bool $isRetain = true ):self {
		$this->fieldReset();
		//
		return $this->addField( $field, $isAutoAlias, $isRetain );
	}

	/**
	 * 重置field
	 * @return $this
	 */
	public function fieldReset():self {
		$this->goModelQuery()->getQuery()->columns = null;
		//
		return $this;
	}

	/**
	 * @param bool $isCleanAllData [true][默认]
	 * @return $this
	 */
	public function cleanAllData( bool $isCleanAllData = true ):self {
		$this->isCleanAllData = $isCleanAllData;
		//
		return $this;
	}

	/**
	 * 是否包含指定field
	 * @param string|null $field [null][默认]全部
	 * @return bool
	 */
	public function hasField( string|null $field = null ):bool {
		//
		$fields = $this->goModelQuery()->getQuery()->columns;
		if( $this->isCleanAllData === false ){
			// 检查*
			if( $fields === null || in_array( $this->buildFieldPrefix( '*' ), $fields ) ){
				return true;
			}
		} else if( $fields === null ){
			return false;
		}
		//
		return in_array( $this->buildFieldPrefix( $field ), $fields );
	}

	/**
	 * 是否包含指定强制保留的field
	 * @param string|null $field [null][默认]全部
	 * @return bool 是否包含
	 */
	public function hasMustRetainField( string|null $field = null ):bool {
		return in_array( $field, $this->mustRetainFields );
	}

	/**
	 * 获取强制保留的field
	 * @return array
	 */
	public function getMustRetainField():array {
		return $this->mustRetainFields;
	}

	/**
	 * 是否包含指定field，不存在则添加
	 * @param string|null $field [null][默认]全部
	 * @param bool $isAutoAlias 字符获取field别名。 [true][必定]
	 * @param bool $isRetain 是否强制保留 [false]否 [true][默认]是
	 * @return $this
	 */
	public function hasFieldOrAdd( string $field = null, bool $isAutoAlias = true, bool $isRetain = true ):self {
		//
		if( ! $this->hasField( $field ) ){
			$this->addField( $field, $isAutoAlias, $isRetain );
		}
		return $this;
	}

	/**
	 * 临时field（数据处理完成后自动销毁）
	 * @param $field
	 * @return $this
	 */
	/*
	public function fieldTemp( $field, bool $isAutoAlias = false ):self {
		// 自动转换别名
		if( $isAutoAlias ){
			$field = $this->getFieldAlias( $field );
		}
		//
		$this->fieldTemp = com\Lib\Fun\Array_::arrayMerge( $this->fieldTemp, is_array( $field ) ? $field : [ $field ] );
		//
		$this->goDbModel()->field( $field );
		//
		return $this;
	}
	*/

	/**
	 * 获取field别名
	 * @param array|string $field
	 * @return array|string
	 */
	public function getFieldAlias( array|string $field ):array|string {
		//		$fieldListsArray = $this->goDbModel()->getOptions( 'field' );
		$fieldListsArray = $this->goModelQuery()->getQuery()->columns;
		//
		if( is_array( $field ) ){
			foreach( $field as $fieldKey => &$fieldValue ){
				/*				if( $fieldValue instanceof \Hyperf\Database\Query\Expression ){
									continue;
								}
								//
								if( is_numeric( $fieldKey ) ){
									$fieldValue = $fieldListsArray[ $fieldValue ] ?? $fieldValue;
									$fieldValue = $this->buildFieldAliasOfCheck( $fieldValue );
								}*/
				if( is_string( $fieldValue ) ){
					$fieldValue = $fieldListsArray[ $fieldValue ] ?? $fieldValue;
					$fieldValue = $this->buildFieldAliasOfCheck( $fieldValue );
				}
			}
			unset( $fieldValue );
		} else{
			/*			if( ! $field instanceof \Hyperf\Database\Query\Expression ){
							$field = $fieldListsArray[ $field ] ?? $field;
							$field = $this->buildFieldAliasOfCheck( $field );
						}*/
			//
			if( is_string( $field ) ){
				$field = $fieldListsArray[ $field ] ?? $field;
				$field = $this->buildFieldAliasOfCheck( $field );
			}
		}
		//
		return $field;
	}

	/**
	 * 增加前缀
	 * @param string $field
	 * @return string
	 */
	public function buildFieldPrefix( string $field ):string {
		if( ! str_contains( $field, $this->getTableName() . '.' ) ){
			return $this->getTableName() . ".{$field}";
		} else{
			return $field;
		}
	}

	/**
	 * 删除前缀
	 * @param string $field
	 * @return string
	 */
	public function delFieldPrefix( string $field ):string {
		$strposValue = strpos( $field, '.' );
		if( $strposValue !== false ){
			return substr( $field, $strposValue + 1 );
		} else{
			return $field;
		}
	}

	/**
	 * 删除前缀(多个)
	 * @param array $fields
	 * @return array
	 */
	public function delFieldPrefixs( array $fields ):array {
		$newFields = [];
		//
		foreach( $fields as $field ){
			$newFields[] = $this->delFieldPrefix( $field );
		}
		//
		return $newFields;
	}

	/**
	 * 自动增加前缀(自动判断是否已包含前缀，未包含时添加)
	 * @param string $field
	 * @return string
	 */
	private function buildFieldAliasOfCheck( string $field ):string {
		if( ! str_contains( $field, '.' ) ){
			return $this->buildFieldPrefix( $field );
		} else{
			return $field;
		}
	}

	/**
	 * 自动增加前缀(自动判断是否已包含前缀，未包含时添加)(多个)
	 * @param array $fields
	 * @return array
	 */
	private function buildFieldAliasOfChecks( array $fields ):array {
		$fieldsRes = [];
		foreach( $fields as $field ){
			$fieldsRes[] = $this->buildFieldAliasOfCheck( $field );
		}
		//
		return $fieldsRes;
	}

	/**
	 * @param string|bool|null $keyName [string]keyName [false]不使用缓存 [null]使用缓存
	 * @param int $expire 缓存过期时间 [null]永久 [3600][默认]
	 * @param bool $isForce 是否强制刷新缓存
	 * @return $this
	 */
	public function cache( string|bool|null $keyName = null, int $expire = 3600, bool $isForce = false ):self {
		$this->goCache()->cache( $keyName, $expire, $isForce );
		//
		return $this;
	}

	/**
	 * @param int|null $expire 缓存过期时间 [null]永久 [3600][默认]
	 * @return $this
	 */
	public function cacheExpire( int|null $expire = 3600 ):self {
		$this->goCache()->cacheExpire( $expire );
		//
		return $this;
	}

	/**
	 * @return nameDataUnit\Cache
	 * @throws
	 */
	public function goCache():nameDataUnit\Cache {
		return $this->goPool( 'goCache', function () {
			return new nameDataUnit\Cache( $this );
		} );
	}

	/**
	 * @param string $sql
	 * @param array $bindings
	 * @param string $boolean
	 * @return $this
	 */
	public function whereRaw( string $sql, array $bindings = [], string $boolean = 'and' ):self {
		$this->goModelQuery()->whereRaw( $sql, $bindings, $boolean );
		//
		return $this;
	}

	/**
	 * 查询多个记录
	 * @param array|string|null $field [null][默认]不指定
	 * @return com\Lib\Hyperf\Model\Collection
	 * @throws
	 */
	public function select( array|string|null $field = null ):com\Lib\Hyperf\Model\Collection {
		if( $field !== null ){
			$this->fieldAndReset( $field );
		}
		// 分页
		$this->goPaginate()->initModelParam();
		// [事件] 之前
		$this->eventDatasBefore();
		// 获取数据
		$dataRes = $this->goCache()->get( $this, function () {
			return $this->goModelQuery()->get()->toArray();
		} );
		// [事件] 之后
		$this->eventDatasLater( $dataRes );
		//
		return com\Lib\Hyperf\Model\Collection::make( $dataRes );
	}

	/**
	 * 查询多个记录
	 * @return array
	 * @throws
	 */
	public function selectToArray():array {
		return $this->select()->toArray();
	}

	/**
	 * 查询多个记录，键名转为短驼峰
	 * @return array
	 * @throws
	 */
	public function selectToArrayAsParse():array {
		return $this->select()->toArrayAsParse();
	}

	/**
	 * 获取原始数据（不进行数据处理）
	 * @return com\Lib\Hyperf\Model\Collection
	 * @throws
	 */
	public function selectRawData():com\Lib\Hyperf\Model\Collection {
		return com\Lib\Hyperf\Model\Collection::make( $this->selectRawDataReArray() );
	}

	/**
	 * 获取原始数据（不进行数据处理），并返回数据
	 * @return array
	 * @throws
	 */
	public function selectRawDataReArray():array {
		return \Hyperf\DbConnection\Db::select( $this->getSql() . ';', $this->goModelQuery()->getBindings() );
	}

	/**
	 * 查找单条记录(不存在则抛出异常)
	 * @return array
	 * @throws
	 */
	public function findOrFailToArray():array {
		return $this->findOrFail()->toArray();
	}

	/**
	 * 查找单条记录，键名转为短驼峰(不存在则抛出异常)
	 * @return array
	 * @throws
	 */
	public function findOrFailToArrayAsParse():array {
		return $this->findOrFail()->toArrayAsParse();
	}

	/**
	 * 查找单条记录(不存在则返回null)
	 * @return com\Lib\Hyperf\Model\Collection | null
	 * @throws
	 */
	public function findOrNull():?com\Lib\Hyperf\Model\Collection {
		return $this->find();
	}


	/**
	 * 查找单条记录(不存在则返回null)
	 * @return array|null
	 * @throws
	 */
	public function findOrNullToArray():?array {
		$data = $this->findOrNull();
		if( $data === null ){
			return null;
		}
		return $data->toArray();
	}

	/**
	 * 查找单条记录，键名转为短驼峰(不存在则返回null)
	 * @return array|null
	 * @throws
	 */
	public function findOrNullToArrayAsParse():?array {
		$data = $this->findOrNull();
		if( $data === null ){
			return null;
		}
		return $data->toArrayAsParse();
	}

	/**
	 * 查找单条记录
	 * @param mixed $default [null]默认值
	 * @return com\Lib\Hyperf\Model\Collection | null
	 * @throws
	 */
	public function find( mixed $default = null ):?com\Lib\Hyperf\Model\Collection {
		// [事件] 之前
		$this->eventDatasBefore();
		// 获取数据
		$dataRes = $this->goCache()->get( $this, function () {
			$res = $this->goModelQuery()->first();
			if( $res === null ){
				return null;
			}
			return $res->toArray();
		} );
		if( empty( $dataRes ) ){
			if( $default === null ){
				return $default;
			}
			return com\Lib\Hyperf\Model\Collection::make( $default );
		}
		// [事件] 之后
		$dataRes = [ $dataRes ];
		$this->eventDatasLater( $dataRes );
		//
		return com\Lib\Hyperf\Model\Collection::make( $dataRes[0] );
	}

	/**
	 * 查找单条记录(不存在则抛出异常)
	 * @return com\Lib\Hyperf\Model\Collection
	 * @throws
	 */
	public function findOrFail():com\Lib\Hyperf\Model\Collection {
		$data = $this->find();
		if( $data === null ){
			throw com\Lib\Err\Exception::makeOfNew( '', com\Lib\Err\Code::$sysSqlDataNotExist );
		}
		//
		return $data;
		/*		// [事件] 之前
				$this->eventDataBefore();
				// 获取数据
				$dataRes = $this->goCache()->get( $this, function(){
					$res = $this->goModelQuery()->first();
					if( empty( $res ) ){
						return null;
					}else{
						return $res->toArray();
					}
				} );
				if( ! empty( $dataRes ) ){
					// [事件] 之后
					$dataRes = [ $dataRes ];
					$this->eventDataLater( $dataRes );
					$dataRes = $dataRes[0] ?? null;
				}
				// 返回
				if( empty( $dataRes ) ){
					throw com\Lib\Err\Exception::makeOfNew( '', com\Lib\Err\Code::$sysSqlDataNotExist );
				}else{
					return com\Lib\Hyperf\Model\Collection::make( $dataRes );
				}*/
	}

	/**
	 * 查找单项数据
	 * @param string $field
	 * @param mixed $default 默认数据。[null][默认]
	 * @return mixed
	 * @throws
	 */
	public function value( string $field, mixed $default = null ) {
		$data = $this->goCache()->get( $this, function () use ( $field ) {
			return $this->goModelQuery()->value( $field );
		} );
		if( $data === null ){
			return $default;
		}
		//
		return $data;
	}

	/**
	 * 查找单项数据（为空时抛出异常）
	 * @param string $field
	 * @return mixed
	 * @throws
	 */
	public function valueOrFail( string $field ):mixed {
		$data = $this->goCache()->get( $this, function () use ( $field ) {
			return $this->goModelQuery()->value( $field );
		} );
		//		if( $data === com\Lib\Com\Code::$varCustomNull ){
		if( $data === null ){
			throw com\Lib\Err\Exception::makeOfNew( '', com\Lib\Err\Code::$sysSqlDataNotExist );
		}
		//
		return $data;
	}

	/**
	 * 获取一列数据
	 * @param string $column 需要获取的列名
	 * @return com\Lib\Hyperf\Model\Collection
	 */
	public function pluk( string $column ):com\Lib\Hyperf\Model\Collection {
		$dataRes = $this->goModelQuery()->pluck( $this->buildFieldPrefix( $column ) )->toArray();
		return com\Lib\Hyperf\Model\Collection::make( $dataRes );
	}

	/**
	 * @param mixed ...$groups 自动加前缀
	 * @return $this
	 */
	public function groupBy( ...$groups ):self {
		$groupsRes = $this->buildFieldAliasOfChecks( $groups );
		$this->goModelQuery()->groupBy( ...$groupsRes );
		//
		return $this;
	}

	/**
	 * Add an "order by" clause to the query.
	 * @param string $column
	 * @param string $direction
	 * @return $this
	 */
	public function orderBy( string $column, string $direction = 'asc' ):self {
		$this->goModelQuery()->orderBy( $column, $direction );
		//
		return $this;
	}

	/**
	 * Add a descending "order by" clause to the query.
	 * @param string $column
	 * @return $this
	 */
	public function orderByDesc( string $column ):self {
		$this->goModelQuery()->orderByDesc( $column );
		//
		return $this;
	}

	/**
	 * Add a descending "order by" clause to the query.
	 * @param string $sql
	 * @param array $bindings
	 * @return $this
	 */
	public function orderByRaw( string $sql, array $bindings = [] ):self {
		$this->goModelQuery()->orderByRaw( $sql, $bindings );
		//
		return $this;
	}

	/**
	 * [事件]获取数据之前
	 * @return void
	 */
	protected function eventDatasBefore():void {
		//
		/*
		$field = $this->goModelQuery()->getQuery()->columns;
		if( $field == '*' || $field === null ){
			$this->goModelQuery()->addSelect( $this->getTableName() . '.*' );
		}
		*/
		//
		$this->fieldClearInit();
		// JoinModel
		$this->goJoinModel()->eventDatasBefore();
		// JoinModelX
		$this->goJoinModelX()->eventDatasBefore();
		// JoinDy
		$this->goJoinDy()->eventDatasBefore();
	}

	/**
	 * [事件]获取数据之后
	 * @param array &$dataRes 源数据
	 * @return void
	 */
	protected function eventDatasLater( array &$dataRes ):void {
		// 记录数据数据字段列表
		$this->recordDataFields( $dataRes );
		// JoinModel
		$dataRes = $this->joinDatas( $dataRes );
		// 销毁临时field
		$this->fieldClear( $dataRes );
	}

	/**
	 * 连接数据
	 * @param array $dataRes 源数据
	 * @return array
	 * @return void
	 */
	public function joinDatas( array $dataRes ):array {
		// JoinModel
		$this->goJoinModel()->eventDatasLater( $dataRes );
		// JoinModelX
		$this->goJoinModelX()->eventDatasLater( $dataRes );
		// JoinDy
		$this->goJoinDy()->eventDatasLater( $dataRes );
		//
		return $dataRes;
	}

	/**
	 * 获取field的真实输出字段名
	 * @param string $field
	 * @return string
	 */
	public function getFieldActualName( string $field ):string {
		return str_replace( $this->getTableName() . ".", '', $field );
	}

	/**
	 * 获取fields的真实输出字段名
	 * @param array $fields
	 * @return array
	 */
	public function getFieldsActualName( array $fields ):array {
		$fieldsActualName = [];
		foreach( $fields as $field ){
			$fieldsActualName[] = str_replace( $this->getTableName() . ".", '', $field );
		}
		return $fieldsActualName;
	}

	/**
	 * field清理初始化
	 * @return bool
	 */
	private function fieldClearInit():bool {
		$this->fieldClearInitData = $this->goModelQuery()->getQuery()->columns;
		return true;
	}

	/**
	 * 记录数据数据字段列表
	 * @param array $array
	 * @return bool
	 */
	private function recordDataFields( array $array ):bool {
		$this->recordDataFields = array_keys( current( $array ) ?: [] );
		return true;
	}

	/**
	 * field清理
	 * @param $dataRes
	 * @return bool
	 */
	private function fieldClear( &$dataRes ):bool {
		// 保留全部
		if( in_array( '*', $this->mustRetainFields ) ){
			return true;
		}
		// 销毁所有数据
		if( $this->isCleanAllData ){
			$waitUnsetField = [];
			foreach( $this->recordDataFields as $recordDataField ){
				// 检查是否为必须保留field
				if( ! in_array( $recordDataField, $this->mustRetainFields ) ){
					$waitUnsetField[] = $recordDataField;
				}
			}
			// 销毁
			foreach( $dataRes as &$quoteDataValue ){
				foreach( $waitUnsetField as $waitUnsetFieldValue ){
					unset( $quoteDataValue[ $waitUnsetFieldValue ] );
				}
			}
			//
			return true;
		}
		//
		// 销毁部分数据
		if( $this->fieldClearInitData == '*' || empty( $this->fieldClearInitData ) ) return true;
		// 转为真实数据字段名
		$fieldClearBefore = [];
		foreach( $this->fieldClearInitData as $fieldName ){
			if( ! is_string( $fieldName ) ){
				continue;
			}
			//
			$fielddActualName = $this->getFieldActualName( $fieldName );
			if( $fielddActualName == '*' ) return true; // 不需要过滤
			$fieldClearBefore[] = $fielddActualName;
		}
		// ...
		$fieldLater = $this->goModelQuery()->getQuery()->columns;
		if( $fieldLater == '*' ) return true;;
		// 对比需要销毁的field
		$waitUnsetField = [];
		foreach( $fieldLater as $fieldLaterValue ){
			if( ! is_string( $fieldLaterValue ) ){
				continue;
			}
			//
			$fieldLaterValue = $this->getFieldActualName( $fieldLaterValue );
			// 检查是否为必须保留field
			if( in_array( $fieldLaterValue, $this->mustRetainFields ) ){
				continue;
			}
			// 是否为系统新增
			if( ! in_array( $fieldLaterValue, $fieldClearBefore ) ){
				$waitUnsetField[] = $fieldLaterValue;
				continue;
			}
			// 检查是否为指定的临时field
			if( in_array( $fieldLaterValue, $this->tempFields ) ){
				$waitUnsetField[] = $fieldLaterValue;
				continue;
			}
		}
		// 销毁
		foreach( $dataRes as &$quoteDataValue ){
			foreach( $waitUnsetField as $waitUnsetFieldValue ){
				unset( $quoteDataValue[ $waitUnsetFieldValue ] );
			}
		}
		//
		return true;
	}

	/**
	 * 是否为创建
	 * @return bool
	 */
	/*
	private function isCreate(  ) {
		return $this->_dataId > 0 ? false : true;
	}
	*/

	/**
	 * 重置数据待保存的数据
	 * @return $this
	 */
	protected function resetSetData():self {
		$this->goDataset()->reset();
		//
		return $this;
	}

	/**
	 * 创建数据
	 * @param array $extraSaveData 额外附加的数据
	 * @return static
	 * @throws
	 */
	protected function saveOfCreate( array $extraSaveData = [] ):static {
		return new static( $this->saveOfCreateReId( $extraSaveData ) );
	}

	/**
	 * 创建数据
	 * @param array $extraSaveData
	 * @return int 返回数据id
	 * @throws
	 */
	protected function saveOfCreateReId( array $extraSaveData = [] ):int {
		// 检查
		if( ! $this->isAllowCreate() ){
			throw com\Lib\Err\Exception::makeOfNew( 'dataUnit模式为不允许创建', com\Lib\Err\Code::$undefined );
		}
		//
		$saveData = $this->goDataset()->getUpdateData( true, false );
		//
		if( ! empty( $extraSaveData ) ){
			$saveData = com\Lib\Fun\Array_::arrayMerges( $saveData, $extraSaveData );
		}
		$dataRes = $this->getModelClassPath()::createX( $saveData );
		if( $dataRes->id === null ){
			throw com\Lib\Err\Exception::makeOfNew( '', com\Lib\Err\Code::$sysSqlInsertError );
		}
		//
		return $dataRes->id;
	}

	/**
	 * 检查是否允许更新
	 * @throws
	 */
	private function checkAllowUpdate():void {
		// 检查
		if( ! $this->isAllowUpdate() ){
			throw com\Lib\Err\Exception::makeOfNew( 'dataUnit模式为不允许修改', com\Lib\Err\Code::$undefined );
		}
		// 检查是否加入where条件
		if( empty( $this->goModelQuery()->getQuery()->wheres ) ){
			throw com\Lib\Err\Exception::makeOfNew( '必须存在where条件', com\Lib\Err\Code::$undefined );
		}
	}

	/**
	 * 获取wheres条件
	 * @return array
	 */
	public function getWheres():array {
		return $this->goModelQuery()->getQuery()->wheres;
	}

	/**
	 * 获取where条件
	 * @param string $whereKey 读取指定的whereKey。如果不存在则返回null
	 * @param mixed $default 默认值。[null][默认]
	 * @return mixed|array|null
	 */
	public function getWhere( string $whereKey, mixed $default = null ):mixed {
		$whereDatas = $this->goModelQuery()->getQuery()->wheres;
		foreach( $whereDatas as $whereValue ){
			if( $whereValue['operator'] === '=' && $this->delFieldPrefix( $whereValue['column'] ) === $whereKey ){
				return $whereValue['value'];
			}
		}
		//
		return $default;
	}

	/**
	 * 获取where条件(不存在则抛出异常)
	 * @param string|null $whereKey 读取指定的whereKey。如果不存在则返回null
	 * @return mixed|array|null
	 * @throws
	 */
	public function getWhereOrFail( string|null $whereKey = null ):mixed {
		$whereDatas = $this->goModelQuery()->getQuery()->wheres;
		foreach( $whereDatas as $whereValue ){
			if( $whereValue['operator'] === '=' && $this->delFieldPrefix( $whereValue['column'] ) === $whereKey ){
				return $whereValue['value'];
			}
		}
		//
		throw com\Lib\Err\Exception::makeOfNew( 'whereKey不存在', com\Lib\Err\Code::$sysDataNotExist );
	}

	/**
	 * 获取where中条件为eq的数据
	 * 备注：只获取第一层的条件
	 * @param bool $isDelFieldPrefix 是否删除字段前缀
	 * @return array 键名为下划线字段
	 */
	protected function getEqWhereDatas( bool $isDelFieldPrefix = false ):array {
		$eqData = [];
		$wheres = $this->goModelQuery()->getQuery()->wheres;
		if( count( $wheres ) === 1 && $wheres[0]['type'] === 'Nested' ){
			$wheres = $wheres[0]['query']->wheres;
		}
		foreach( $wheres as $whereValue ){
			if( $whereValue['operator'] === '=' ){
				$column = $isDelFieldPrefix ? $this->delFieldPrefix( $whereValue['column'] ) : $whereValue['column'];
				$eqData[ $column ] = $whereValue['value'];
			}
		}
		//
		return $eqData;
	}

	/**
	 * 获取所有where条件数据
	 * @return array
	 */
	/*
	private function getWhereDatas(  ):array {
		return $this->goModelQuery()->getQuery()->wheres;
	}
	*/

	/**
	 * 是否有更新数据
	 * @return bool
	 */
	public function hasUpdateData():bool {
		return ! empty( $this->goDataset()->goFieldStruct()->getChangeStructDatas() );
	}

	/**
	 * 获取更新数据
	 * @param bool $isGetDefaultValue 是否获取默认数据
	 * @param bool $keyNameType [false][默认]将Java风格转换为C的风格 [true]将C风格转换为Java的风格
	 * @return array
	 * @throws
	 */
	public function getUpdateData( bool $isGetDefaultValue = false, bool $keyNameType = true ):array {
		return $this->goDataset()->getUpdateData( $isGetDefaultValue, $keyNameType );
	}

	/**
	 * 更新数据
	 * @param array $extraSaveData 额外附加的数据
	 * @return int 更新影响数
	 * @throws
	 */
	protected function saveOfUpdate( array $extraSaveData = [] ):int {
		// 检查
		$this->checkAllowUpdate();
		// 获取需要更新的数据
		$saveData = $this->getUpdateData( false, false );
		if( ! empty( $extraSaveData ) ){
			$saveData = com\Lib\Fun\Array_::arrayMerges( $saveData, $extraSaveData );
		}
		if( empty( $saveData ) ){
			return 0;
		}
		//
		$saveData = $this->getAttributeDatas( $saveData );
		// 更新
		return $this->goModelQuery()->update( $saveData );
	}

	/**
	 * 更新或创建（不存在时创建）
	 * @param array $updateExtraSaveData 更新时使用的额外附加的数据
	 * @param array $createExtraSaveData 创建时使用的额外附加的数据
	 * @return static
	 * @throws
	 */
	protected function updateOrCreate( array $updateExtraSaveData = [], array $createExtraSaveData = [] ):static {
		// 检查数据是否存在
		$dataId = $this->goModelQuery()->value( 'id' );
		if( $dataId === null ){
			// 创建
			$createExtraSaveData = array_merge( $this->getEqWhereDatas(), $createExtraSaveData );
			return $this->saveOfCreate( $createExtraSaveData );
		} else{
			// 修改
			$this->saveOfUpdate( $updateExtraSaveData );
			return new static( $dataId );
		}
	}

	/**
	 * 获取修改器后的内容
	 * @param array $saveData
	 * @return array
	 */
	protected function getAttributeDatas( array $saveData ):array {
		$modelPath = $this->getModelClassPath();
		$model = new $modelPath;
		foreach( $saveData as $saveKey => $saveValue ){
			if( $saveValue instanceof \Hyperf\Database\Query\Expression ){
				continue;
			}
			$attributesMethodName = 'set' . com\Lib\Fun\Str::parseName( $saveKey, 1 ) . 'Attribute';
			if( method_exists( $model, $attributesMethodName ) ){
				call_user_func( [
					$model,
					$attributesMethodName
				], $saveValue );
			}
		}
		return array_merge( $saveData, $model->getAttributes() );
	}

	/**
	 * 删除
	 * @return int 删除数量
	 * @throws
	 */
	protected function delete():int {
		// 检查是否加入where条件
		if( empty( $this->goModelQuery()->getQuery()->wheres ) ){
			throw com\Lib\Err\Exception::makeOfNew( '删除操作必须存在where条件', com\Lib\Err\Code::$undefined );
		}
		// 删除
		return $this->goModelQuery()->delete();
	}

	/**
	 * 重置field条件
	 * @return void
	 */
	public function resetField():void {
		$this->goModelQuery()->getQuery()->columns = null;
	}

	/**
	 * 重置where条件
	 * @return void
	 */
	public function resetWhereAndSetData():void {
		$this->resetWhere();
		$this->goDataset()->reset();
	}

	/**
	 * 重置where条件
	 * @return void
	 */
	public function resetWhere():void {
		// $this->goModelQuery()->getQuery()->wheres = [];
		$this->goModelQuery()->getQuery()->wheres = [];
		$this->goModelQuery()->getQuery()->bindings['where'] = [];
	}

	/**
	 * where是否为空
	 * @return bool
	 */
	public function isEmptyWhere():bool {
		return empty( $this->goModelQuery()->getQuery()->wheres );
	}

	/**
	 * 获取sql语句
	 * @return string
	 */
	public function getSql():string {
		return $this->goModelQuery()->toSql();
	}

	/**
	 * 获取完整sql语句
	 * @return string
	 */
	public function getFullSql():string {
		$bindings = $this->goModelQuery()->getBindings();
		//
		$bindings = array_map( function ( $value ) {
			if( is_string( $value ) ){
				// 字符串加引号
				return '\'' . $value . '\'';
			} else{
				return $value;
			}
		}, $bindings );
		//
		$sql = str_replace( '?', '%s', $this->getSql() );
		return vsprintf( $sql, $bindings );
	}

	/**
	 * 输出完整sql语句
	 * @return $this
	 */
	public function echoFullSql():self {
		d( $this->getFullSql() );
		return $this;
	}

	/**
	 * 魔术方法->call
	 * @param string $name 方法名
	 * @param array $args 参数
	 * @return mixed||Exception 返回数据(可能抛出的异常:[get*]com\Cla\Err\Code::$sysDataErrorSeverity。[其他]com\Cla\Err\Code::$sysFunExecuteError)
	 */
	/*
	public function __call( $name, $args ) {
		$callRes = $this->_dataOperate_Call( $name, $args, com\Lib\Com\Code::$varCustomNull );
		if( $callRes !== com\Lib\Com\Code::$varCustomNull ){
			return $callRes;
		}
		//
		$returnThisMethod = [ 'field', 'where', 'order' ];
		//
		$res = $this->goModelQuery()->$name( ...$args );
		if( array_search( $name, $returnThisMethod ) !== false ){
			return $this;
		}else{
			return $res;
		}
	}
	*/

	/**
	 * 是否使用缓存
	 * @return bool|null [true]使用 [false]未使用 [null]未设置
	 */
	public function isUseCache():?bool {
		return $this->goModelQuery()->isUseCache();
	}

	/**
	 * 获取缓存时间属性
	 * @return Carbon|int|bool|null
	 */
	public function getCacheTime():Carbon|int|bool|null {
		return $this->goModelQuery()->getCacheTime();
	}

	/**
	 * 获取当前类路径名
	 * @return string
	 */
	public function getPath():string {
		return static::class;
	}

	/**
	 * 设置where
	 * @param array|\Closure|string $column
	 * @param string|null $operator
	 * @param mixed $value
	 * @param string $boolean
	 * @return $this
	 */
	public function where( array|\Closure|string $column, string|null $operator = null, mixed $value = null, string $boolean = 'and' ):self {
		if( $column instanceof \Closure ){
			$this->goModelQuery()->where( $column );
		} else{
			// 转成string类型，因框架内部使用 strtolower 会出现类型错误
			if( $value === null && is_numeric( $operator ) ){
				$operator = (string)$operator;
			}
			if( is_numeric( $value ) ){
				$value = (string)$value;
			}
			//
			$this->goModelQuery()->where( $this->getTableName() . '.' . $column, $operator, $value, $boolean );
		}
		//
		return $this;
	}

	/**
	 * @param int $value
	 * @return $this
	 */
	public function offset( int $value ):self {
		$this->goModelQuery()->offset( $value );
		//
		return $this;
	}

	/**
	 * @param int $value
	 * @return $this
	 */
	public function limit( int $value ):self {
		$this->goModelQuery()->limit( $value );
		//
		return $this;
	}

}
